package club.xyes.zkh.ecommerce.web.api.controller;

import club.xyes.zkh.ecommerce.commons.context.ApplicationConstants;
import club.xyes.zkh.ecommerce.commons.dto.MinimalUserInfo;
import club.xyes.zkh.ecommerce.commons.entity.TransactionLog;
import club.xyes.zkh.ecommerce.commons.entity.User;
import club.xyes.zkh.ecommerce.commons.entity.UserMembership;
import club.xyes.zkh.ecommerce.commons.util.EmojiUtil;
import club.xyes.zkh.ecommerce.commons.util.TextUtil;
import club.xyes.zkh.ecommerce.commons.vo.GeneralResult;
import club.xyes.zkh.ecommerce.commons.vo.TransactionLogOverview;
import club.xyes.zkh.ecommerce.security.encoder.AccessTokenEncoder;
import club.xyes.zkh.ecommerce.service.TransactionLogService;
import club.xyes.zkh.ecommerce.service.UserCouponService;
import club.xyes.zkh.ecommerce.service.UserMembershipService;
import club.xyes.zkh.ecommerce.service.UserService;
import club.xyes.zkh.ecommerce.web.api.vo.SetUserPhoneVo;
import club.xyes.zkh.ecommerce.web.controller.BaseController;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Create by 郭文梁 2019/4/16 0016 17:08
 * UserController
 * 用户相关数据访问控制器
 *
 * @author 郭文梁
 * @data 2019/4/16 0016
 */
@RestController
@RequestMapping("/api/user")
@Api("用户相关接口")
public class UserController extends BaseController<User> {
    private final UserService userService;
    private final AccessTokenEncoder accessTokenEncoder;
    private final UserCouponService userCouponService;
    private final TransactionLogService transactionLogService;
    private final UserMembershipService userMembershipService;

    public UserController(UserService userService,
                          AccessTokenEncoder accessTokenEncoder,
                          UserCouponService userCouponService,
                          TransactionLogService transactionLogService,
                          UserMembershipService userMembershipService) {
        super(userService);
        this.userService = userService;
        this.accessTokenEncoder = accessTokenEncoder;
        this.userCouponService = userCouponService;
        this.transactionLogService = transactionLogService;
        this.userMembershipService = userMembershipService;
    }

    /**
     * 通过微信小程序获得的code登录
     *
     * @param code 临时code
     * @return 用户信息
     * @throws IOException IO异常
     */
    @PostMapping("/_login-by-micro-program-code")
    @ApiOperation("通过微信小程序获得的code登录")
    public GeneralResult<Map<String, Object>> loginByMicroProgramCode(@RequestParam("code") String code, String oauthCode) throws IOException {
        Map<String, Object> res = new HashMap<>(2);
        User user = userService.loginByMicroProgramCode(code);
        if (oauthCode != null) {
            user = userService.bindOauthOpenId(user, code);
        }
        res.put("user", user);
        res.put("accessToken", accessTokenEncoder.encode(MinimalUserInfo.fromUser(user).toJSON(), ApplicationConstants.Security.TOKEN_USER_PREFIX));
        return GeneralResult.ok(res);
    }

    /**
     * 完善用户的头像 用户名等信息
     *
     * @param user 用户对象(avatar, name )
     * @return user
     */
    @PostMapping("/_complement")
    @ApiOperation("完善用户信息")
    public GeneralResult<User> complement(@RequestBody User user) {
        if (user == null || user.getAvatar() == null || user.getName() == null) {
            return GeneralResult.badRequest("Incomplete parameters!", user);
        }
        MinimalUserInfo userInfo = getUserInfo();
        assert userInfo != null;
        String openid = userInfo.getWxOpenId();
        String avatar = user.getAvatar();
        String name = EmojiUtil.filterEmoji(user.getName());
        User res = userService.complementByOpenId(openid, avatar, name);
        return GeneralResult.ok(res);
    }

    /**
     * 获取当前登录的用户
     *
     * @return GR
     */
    @GetMapping("/me")
    @ApiOperation("获取当前登录的用户")
    public GeneralResult<User> me() {
        User user = currentUser();
        return GeneralResult.ok(user);
    }

    /**
     * 更新用户信息
     *
     * @param param (name必填 mobile非必填)
     * @return GR
     */
    @PostMapping("/update")
    @ApiOperation("更新当前用户的信息")
    public GeneralResult<User> update(@RequestBody User param) {
        if (param == null || TextUtil.isTrimedEmpty(param.getName())) {
            return GeneralResult.badRequest("缺少参数");
        }
        User user = currentUser();
        user.setName(param.getName());
        user.setMobile(param.getMobile());
        User res = userService.updateById(user);
        return GeneralResult.ok(res);
    }

    /**
     * 查询用户的令牌 开发时需要 上线后移除
     *
     * @param id 用户ID
     * @return 令牌
     */
    @GetMapping("/{id}/token")
    public GeneralResult<String> myToken(@PathVariable("id") Integer id) {
        User user = userService.getRequired(id);
        MinimalUserInfo userInfo = MinimalUserInfo.fromUser(user);
        String token = accessTokenEncoder.encode(userInfo.toJSON());
        return GeneralResult.ok(token);
    }

    /**
     * 获取当前用户
     *
     * @return 用户
     */
    private User currentUser() {
        return userService.getRequired(getRequiredUserInfo().getUserId());
    }

    /**
     * 设置用户的手机号码
     *
     * @param param {mobile: 13211111111}
     * @return GR
     */
    @PostMapping("/set-mobile")
    @ApiOperation("设置用户手机号")
    public GeneralResult<User> setMobile(@RequestBody SetUserPhoneVo param) {
        if (param == null || TextUtil.isTrimedEmpty(param.getData()) || TextUtil.isTrimedEmpty(param.getIv())) {
            return GeneralResult.badRequest("缺少参数");
        }
        User user = currentUser();
        user = userService.setMobile(user, param.getIv(), param.getData());
        return GeneralResult.ok(user);
    }

    /**
     * 查询商铺端用户概览信息
     *
     * @param userId 用户ID
     * @param shopId 商铺ID
     * @return GR
     */
    @ApiOperation("查询商铺端用户概览信息")
    @GetMapping("/{userId}/shop/{shopId}")
    public GeneralResult<Map<String, Object>> overview4Shop(@PathVariable("userId") Integer userId,
                                                            @PathVariable("shopId") Integer shopId,
                                                            Integer page, Integer rows) {
        page = page == null ? DEFAULT_PAGE : page;
        rows = rows == null ? DEFAULT_ROWS : rows;
        User user = userService.getRequired(userId);
        int couponCount = userCouponService.countByUserAndShop(userId, shopId);
        TransactionLogOverview transactionLogOverview = transactionLogService.overviewByShopAndUser(shopId, userId);
        PageInfo<TransactionLog> logs = transactionLogService.findByUserAndShop(userId, shopId, page, rows);
        List<UserMembership> memberships = userMembershipService.findByUserIdAndShopIdFetchAll(userId, shopId);
        Map<String, Object> res = new HashMap<>(6);
        res.put("user", user);
        res.put("couponCount", couponCount);
        res.put("membershipCount", memberships.size());
        res.put("memberships", memberships);
        res.put("transactionLogOverview", transactionLogOverview);
        res.put("logs", logs);
        return GeneralResult.ok(res);
    }
}
